home *** CD-ROM | disk | FTP | other *** search
- /*
- * wavfilt.c --- pre-compresser for MicroSoft WaveForm-File
- * (16bit 44100Hz monoral)
- *
- * (開発履歴) V2.2 by Togo(とご) [電脳わ~るど]
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <limits.h>
-
- /* コンパイル条件 */
- // 量子化の手段として16で割る
- #define Q16
- //#define NOQ
- // 0のランレングス圧縮等を行う
- #define LL
-
- /* 作業ブロック単位 */
- #define N 65536
- #define M N/32
- #ifdef NOQ
- #define QMAX 1
- #define QMIN 1
- #else
- #ifdef Q2
- #define QMIN 2
- #define QMAX 4
- #endif
- #ifdef Q4
- #define QMIN 4
- #define QMAX 8
- #endif
- #ifdef Q8
- #define QMIN 8
- #define QMAX 16
- #endif
- #ifdef Q16
- #define QMIN 16
- #define QMAX 32
- #endif
- #ifdef Q32
- #define QMIN 32
- #define QMAX 64
- #endif
- #ifdef Q64
- #define QMIN 64
- #define QMAX 128
- #endif
- #endif
-
- static FILE *infile,*outfile;
-
- /* 作業用バッファ */
- static short buffer[N],
- buf1_1[N/2],buf1_2[N/2],
- buf2_1[N/4],buf2_2[N/4],buf2_3[N/4],buf2_4[N/4],
- buf3_1[N/8],buf3_2[N/8],buf3_3[N/8],buf3_4[N/8],
- buf3_5[N/8],buf3_6[N/8],
- buf4_1[N/16],buf4_2[N/16],buf4_3[N/16],buf4_4[N/16],
- buf4_5[N/16],buf4_6[N/16],buf4_7[N/16],buf4_8[N/16],
- buf4_9[N/16],buf4_10[N/16],
- buf5_1[N/32],buf5_2[N/32],buf5_3[N/32],buf5_4[N/32],
- buf5_5[N/32],buf5_6[N/32],buf5_7[N/32],buf5_8[N/32],
- buf5_9[N/32],buf5_10[N/32],buf5_11[N/32],buf5_12[N/32],
- buf5_13[N/32],buf5_14[N/32],buf5_15[N/32],buf5_16[N/32],
- buf5_17[N/32],buf5_18[N/32];
-
-
- /* 超簡単フィルタ */
- void filtering(short *a,short *b,short *c,unsigned long d)
- {
- int t,s;
-
- for(t = 0,s = 0; s < d; t+=2,s++){
- b[s] = (a[t+1] + a[t] )/2;
- c[s] = (a[t+1] - a[t] )/2;
- }
- }
-
- /* 超簡単アンチフィルタ */
- void untifilt(short *a,short *b,short *c,unsigned long d)
- {
- int t,s;
-
- for(t = 0,s = 0; t < d; t++,s+=2){
- c[s] = a[t] - b[t];
- c[s+1] = a[t] + b[t];
- }
- }
-
- /* ランレングス圧縮書き込み */
- void cswrite(short *buf)
- {
- int t,s,square,flag,ctr;
- short tmp;
- int X[M];
-
- t = 0;
- flag = 0;
- square = 0;
-
- for(ctr = 0;ctr < M;ctr++){
- square += (int)buf[ctr]*buf[ctr];
- }
- tmp = (short)(sqrt((double)(square/M)))+1;
- if(tmp < QMIN)tmp = QMIN;
- if(tmp > QMAX)tmp = QMAX;
- fwrite(&tmp,2,1,outfile);
- for(ctr = 0;ctr < M;ctr++){
- buf[ctr] /= tmp;
- }
- #ifdef LL
- for(ctr = 0;ctr < M;ctr++){
- /* 2バイト読む */
- tmp = buf[ctr];
- /* 127より上または-127より下のとき 0x80を出力して自身を出力する */
- if(tmp > 127 || tmp < -127){
- if(flag == 1){
- fputc(t,outfile);
- flag = 0;
- }
- fputc(0x80,outfile);
- fwrite(&tmp,2,1,outfile);
- }else{
- if((tmp == 0) && (t < 255)){
- // ランレングスモードの可能性あり
- if(flag == 1){
- // ランレングスモード中
- t++;
- }else{
- // ランレングスモードに入る
- fputc((int)tmp,outfile);
- t = 0;
- flag = 1;
- }
- }else{
- // ランレングスモード脱出の可能性あり
- if(flag == 1){
- // ランレングスモード脱出
- fputc(t,outfile);
- if(t == 255){
- // ランレングスモードに再び入れるように
- ctr--;
- // 今の値をキャンセルする
- t = 0;
- }else{
- fputc(tmp,outfile);
- }
- flag = 0;
- }else{
- // 元からモードでなかった(^^;とき
- fputc(tmp,outfile);
- }
- }
- }
- }
- if(flag == 1){
- fputc(t,outfile);
- }
- #else
- for(ctr = 0;ctr < M;ctr++){
- /* 2バイト読む */
- tmp = buf[ctr];
- fwrite(&tmp,2,1,outfile);
- }
- #endif
- }
-
- /* 読み込みランレングス伸長 */
- void csread(short *buf)
- {
- int c,t,ctr,s;
- short tmp;
- int X[M];
- fread(&tmp,2,1,infile);
-
- #ifdef LL
- for(ctr = 0;ctr < M;){
- c = fgetc(infile);
- switch(c){
- case 0x80:
- fread(&buf[ctr],2,1,infile);
- buf[ctr] *= tmp;
- ctr++;
- break;
- case 0x00:
- c = fgetc(infile);
- for(t = 0; t < (c & 0xff)+1; t++){
- buf[ctr] = 0;
- ctr++;
- }
- break;
- default:
- buf[ctr] = (short)((signed char)c);
- buf[ctr] *= tmp;
- ctr++;
- break;
- }
- }
- #else
- for(ctr = 0;ctr < M;ctr++){
- fread(&buf[ctr],2,1,infile);
- buf[ctr] *= tmp;
- }
- #endif
-
-
- }
-
- void encode(unsigned long size)
- {
- unsigned long i,p,q,r,s,t;
- unsigned long m = size / N;
- unsigned long n = size % N;
-
- for(i = 0; i < m; ++i){
- fread((void *)&buffer[0],N*2,1,infile);
- filtering(buffer,buf1_1,buf1_2,N/2);
-
- filtering(buf1_1,buf2_1,buf2_2,N/4);
- filtering(buf1_2,buf2_3,buf2_4,N/4);
-
- filtering(buf2_1,buf3_1,buf3_2,N/8);
- filtering(buf2_2,buf3_3,buf3_4,N/8);
- filtering(buf2_3,buf3_5,buf3_6,N/8);
-
- filtering(buf3_1,buf4_1,buf4_2,N/16);
- filtering(buf3_2,buf4_3,buf4_4,N/16);
- filtering(buf3_3,buf4_5,buf4_6,N/16);
- filtering(buf3_4,buf4_7,buf4_8,N/16);
- filtering(buf3_5,buf4_9,buf4_10,N/16);
-
- filtering(buf4_1,buf5_1,buf5_2,N/32);
- filtering(buf4_2,buf5_3,buf5_4,N/32);
- filtering(buf4_3,buf5_5,buf5_6,N/32);
- filtering(buf4_4,buf5_7,buf5_8,N/32);
- filtering(buf4_5,buf5_9,buf5_10,N/32);
- filtering(buf4_6,buf5_11,buf5_12,N/32);
- filtering(buf4_7,buf5_13,buf5_14,N/32);
- filtering(buf4_8,buf5_15,buf5_16,N/32);
- filtering(buf4_9,buf5_17,buf5_18,N/32);
-
- cswrite(buf5_1);
- cswrite(buf5_2);
- cswrite(buf5_3);
- cswrite(buf5_4);
- cswrite(buf5_5);
- cswrite(buf5_6);
- cswrite(buf5_7);
- cswrite(buf5_8);
- cswrite(buf5_9);
- cswrite(buf5_10);
- cswrite(buf5_11);
- cswrite(buf5_12);
- cswrite(buf5_13);
- cswrite(buf5_14);
- cswrite(buf5_15);
- cswrite(buf5_16);
- cswrite(buf5_17);
- cswrite(buf5_18);
- }
- for(i = 0; i < N; ++i) buffer[i] = 0;
- fread((void *)&buffer[0],n*2,1,infile);
- filtering(buffer,buf1_1,buf1_2,N/2);
-
- filtering(buf1_1,buf2_1,buf2_2,N/4);
- filtering(buf1_2,buf2_3,buf2_4,N/4);
-
- filtering(buf2_1,buf3_1,buf3_2,N/8);
- filtering(buf2_2,buf3_3,buf3_4,N/8);
- filtering(buf2_3,buf3_5,buf3_6,N/8);
-
- filtering(buf3_1,buf4_1,buf4_2,N/16);
- filtering(buf3_2,buf4_3,buf4_4,N/16);
- filtering(buf3_3,buf4_5,buf4_6,N/16);
- filtering(buf3_4,buf4_7,buf4_8,N/16);
- filtering(buf3_5,buf4_9,buf4_10,N/16);
-
- filtering(buf4_1,buf5_1,buf5_2,N/32);
- filtering(buf4_2,buf5_3,buf5_4,N/32);
- filtering(buf4_3,buf5_5,buf5_6,N/32);
- filtering(buf4_4,buf5_7,buf5_8,N/32);
- filtering(buf4_5,buf5_9,buf5_10,N/32);
- filtering(buf4_6,buf5_11,buf5_12,N/32);
- filtering(buf4_7,buf5_13,buf5_14,N/32);
- filtering(buf4_8,buf5_15,buf5_16,N/32);
- filtering(buf4_9,buf5_17,buf5_18,N/32);
-
- cswrite(buf5_1);
- cswrite(buf5_2);
- cswrite(buf5_3);
- cswrite(buf5_4);
- cswrite(buf5_5);
- cswrite(buf5_6);
- cswrite(buf5_7);
- cswrite(buf5_8);
- cswrite(buf5_9);
- cswrite(buf5_10);
- cswrite(buf5_11);
- cswrite(buf5_12);
- cswrite(buf5_13);
- cswrite(buf5_14);
- cswrite(buf5_15);
- cswrite(buf5_16);
- cswrite(buf5_17);
- cswrite(buf5_18);
- }
-
- void decode(unsigned long size)
- {
- unsigned long i;
-
- unsigned long m = size / N;
- unsigned long n = size % N;
-
- for(i = 0; i < m; ++i){
- csread(buf5_1);
- csread(buf5_2);
- csread(buf5_3);
- csread(buf5_4);
- csread(buf5_5);
- csread(buf5_6);
- csread(buf5_7);
- csread(buf5_8);
- csread(buf5_9);
- csread(buf5_10);
- csread(buf5_11);
- csread(buf5_12);
- csread(buf5_13);
- csread(buf5_14);
- csread(buf5_15);
- csread(buf5_16);
- csread(buf5_17);
- csread(buf5_18);
-
- untifilt(buf5_17,buf5_18,buf4_9,N/32);
- untifilt(buf5_15,buf5_16,buf4_8,N/32);
- untifilt(buf5_13,buf5_14,buf4_7,N/32);
- untifilt(buf5_11,buf5_12,buf4_6,N/32);
- untifilt(buf5_9,buf5_10,buf4_5,N/32);
- untifilt(buf5_7,buf5_8,buf4_4,N/32);
- untifilt(buf5_5,buf5_6,buf4_3,N/32);
- untifilt(buf5_3,buf5_4,buf4_2,N/32);
- untifilt(buf5_1,buf5_2,buf4_1,N/32);
-
- untifilt(buf4_9,buf4_10,buf3_5,N/16);
- untifilt(buf4_7,buf4_8,buf3_4,N/16);
- untifilt(buf4_5,buf4_6,buf3_3,N/16);
- untifilt(buf4_3,buf4_4,buf3_2,N/16);
- untifilt(buf4_1,buf4_2,buf3_1,N/16);
-
- untifilt(buf3_5,buf3_6,buf2_3,N/8);
- untifilt(buf3_3,buf3_4,buf2_2,N/8);
- untifilt(buf3_1,buf3_2,buf2_1,N/8);
-
- untifilt(buf2_3,buf2_4,buf1_2,N/4);
- untifilt(buf2_1,buf2_2,buf1_1,N/4);
-
- untifilt(buf1_1,buf1_2,buffer,N/2);
- fwrite((void *)&buffer[0],N*2,1,outfile);
- }
- csread(buf5_1);
- csread(buf5_2);
- csread(buf5_3);
- csread(buf5_4);
- csread(buf5_5);
- csread(buf5_6);
- csread(buf5_7);
- csread(buf5_8);
- csread(buf5_9);
- csread(buf5_10);
- csread(buf5_11);
- csread(buf5_12);
- csread(buf5_13);
- csread(buf5_14);
- csread(buf5_15);
- csread(buf5_16);
- csread(buf5_17);
- csread(buf5_18);
-
- untifilt(buf5_17,buf5_18,buf4_9,N/32);
- untifilt(buf5_15,buf5_16,buf4_8,N/32);
- untifilt(buf5_13,buf5_14,buf4_7,N/32);
- untifilt(buf5_11,buf5_12,buf4_6,N/32);
- untifilt(buf5_9,buf5_10,buf4_5,N/32);
- untifilt(buf5_7,buf5_8,buf4_4,N/32);
- untifilt(buf5_5,buf5_6,buf4_3,N/32);
- untifilt(buf5_3,buf5_4,buf4_2,N/32);
- untifilt(buf5_1,buf5_2,buf4_1,N/32);
-
- untifilt(buf4_9,buf4_10,buf3_5,N/16);
- untifilt(buf4_7,buf4_8,buf3_4,N/16);
- untifilt(buf4_5,buf4_6,buf3_3,N/16);
- untifilt(buf4_3,buf4_4,buf3_2,N/16);
- untifilt(buf4_1,buf4_2,buf3_1,N/16);
-
- untifilt(buf3_5,buf3_6,buf2_3,N/8);
- untifilt(buf3_3,buf3_4,buf2_2,N/8);
- untifilt(buf3_1,buf3_2,buf2_1,N/8);
-
- untifilt(buf2_3,buf2_4,buf1_2,N/4);
- untifilt(buf2_1,buf2_2,buf1_1,N/4);
-
- untifilt(buf1_1,buf1_2,buffer,N/2);
- fwrite((void *)&buffer[0],n*2,1,outfile);
- }
-
- int main(int argc, char *argv[])
- {
- int i,j;
- int ed_flag;
- char *s,*input_filename,*output_filename;
- unsigned long size; /* 元のバイト数 */
- char head[44];
-
- ed_flag = 0;
-
- if(argc != 4){
- exit(-1);
- }
-
- s = argv[1];
- if(s[0] == '-'){
- for(j = 1; s[j]; ++j){
- switch(s[j]){
- /* 現れたもの勝ち */
-
- case 'e': ed_flag = 1;
- break;
-
- case 'd': ed_flag = -1;
- break;
-
- default: ;
- }
- }
- }
-
- if ((infile = fopen(argv[2], "rb")) == NULL){
- exit(-1);
- }
- if ((outfile = fopen(argv[3], "wb")) == NULL){
- exit(-1);
- }
-
- if (ed_flag == 1) {
- fread(head,44,1,infile);
- fwrite(head,44,1,outfile);
- fseek(infile, 0L, SEEK_END); /* infile の末尾を探す */
- size = ftell(infile); /* infile のバイト数 */
- fwrite(&size, sizeof size, 1, outfile);
- fseek(infile,44,SEEK_SET);
- encode((size-44)/2); /* 圧縮 */
- } else if(ed_flag == -1){
- fread(head,44,1,infile);
- fwrite(head,44,1,outfile);
- fread(&size, sizeof size, 1, infile); /* 元のバイト数 */
- decode((size-44)/2); /* 復元 */
- }
- fclose(infile); fclose(outfile);
- return EXIT_SUCCESS;
- }